package com.uniflow.service;


import com.uniflow.entity.DataSync;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * 数据同步调度器
 */
@Service
public class DataSyncScheduler {
    
    private static final Logger logger = LoggerFactory.getLogger(DataSyncScheduler.class);
    
    @Autowired
    private DataSyncService dataSyncService;
    
    @Autowired
    private DataSyncExecutor dataSyncExecutor;
    
    // 调度器线程池
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(5);
    
    // 存储已调度的任务
    private final ConcurrentHashMap<String, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();
    
    /**
     * 初始化调度器
     */
    @PostConstruct
    public void init() {
        logger.info("数据同步调度器初始化开始");
        
        // 加载所有启用的定时同步任务
        loadScheduledTasks();
        
        logger.info("数据同步调度器初始化完成");
    }
    
    /**
     * 销毁调度器
     */
    @PreDestroy
    public void destroy() {
        logger.info("数据同步调度器销毁开始");
        
        // 取消所有调度任务
        cancelAllScheduledTasks();
        
        // 关闭调度器
        scheduler.shutdown();
        try {
            if (!scheduler.awaitTermination(60, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
            Thread.currentThread().interrupt();
        }
        
        logger.info("数据同步调度器销毁完成");
    }
    
    /**
     * 加载所有调度任务
     */
    public void loadScheduledTasks() {
        try {
            // 获取所有启用的定时同步任务
            List<DataSync> scheduledSyncs = dataSyncService.getScheduledSyncs(null);
            
            for (DataSync dataSync : scheduledSyncs) {
                scheduleTask(dataSync);
            }
            
            logger.info("加载了 {} 个定时同步任务", scheduledSyncs.size());
        } catch (Exception e) {
            logger.error("加载调度任务失败", e);
        }
    }
    
    /**
     * 调度单个任务
     */
    public boolean scheduleTask(DataSync dataSync) {
        try {
            if (!dataSync.isEnabled() || !dataSync.isScheduled()) {
                return false;
            }
            
            // 取消已存在的调度
            cancelScheduledTask(dataSync.getId());
            
            // 解析调度配置
            DataSync.ScheduleConfig scheduleConfig = dataSync.getScheduleConfigObject();
            if (scheduleConfig == null) {
                logger.warn("同步任务 {} 缺少调度配置", dataSync.getName());
                return false;
            }
            
            String scheduleType = scheduleConfig.getType();
            
            ScheduledFuture<?> future = null;
            
            switch (scheduleType.toLowerCase()) {
                case "cron":
                    future = scheduleCronTask(dataSync, scheduleConfig);
                    break;
                case "interval":
                    future = scheduleIntervalTask(dataSync, scheduleConfig);
                    break;
                case "fixed_rate":
                    future = scheduleFixedRateTask(dataSync, scheduleConfig);
                    break;
                case "fixed_delay":
                    future = scheduleFixedDelayTask(dataSync, scheduleConfig);
                    break;
                case "once":
                    future = scheduleOnceTask(dataSync, scheduleConfig);
                    break;
                default:
                    logger.warn("不支持的调度类型: {}", scheduleType);
                    return false;
            }
            
            if (future != null) {
                scheduledTasks.put(dataSync.getId(), future);
                logger.info("成功调度同步任务: {} ({})", dataSync.getName(), scheduleType);
                return true;
            }
            
        } catch (Exception e) {
            logger.error("调度任务失败: {}", dataSync.getName(), e);
        }
        
        return false;
    }
    
    /**
     * Cron表达式调度
     */
    private ScheduledFuture<?> scheduleCronTask(DataSync dataSync, DataSync.ScheduleConfig scheduleConfig) {
        String cronExpression = scheduleConfig.getCronExpression();
        
        // 这里简化处理，实际应该使用Cron解析器
        // 为了演示，我们使用固定间隔模拟
        long intervalSeconds = parseCronToInterval(cronExpression);
        
        return scheduler.scheduleAtFixedRate(
            () -> executeScheduledTask(dataSync),
            0,
            intervalSeconds,
            TimeUnit.SECONDS
        );
    }
    
    /**
     * 间隔调度
     */
    private ScheduledFuture<?> scheduleIntervalTask(DataSync dataSync, DataSync.ScheduleConfig scheduleConfig) {
        long interval = scheduleConfig.getIntervalSeconds() != null ? scheduleConfig.getIntervalSeconds() : 60;
        String timeUnit = "SECONDS";
        
        TimeUnit unit = parseTimeUnit(timeUnit);
        
        return scheduler.scheduleAtFixedRate(
            () -> executeScheduledTask(dataSync),
            0,
            interval,
            unit
        );
    }
    
    /**
     * 固定频率调度
     */
    private ScheduledFuture<?> scheduleFixedRateTask(DataSync dataSync, DataSync.ScheduleConfig scheduleConfig) {
        long period = scheduleConfig.getIntervalSeconds() != null ? scheduleConfig.getIntervalSeconds() : 60;
        String timeUnit = "SECONDS";
        long initialDelay = 0;
        
        TimeUnit unit = parseTimeUnit(timeUnit);
        
        return scheduler.scheduleAtFixedRate(
            () -> executeScheduledTask(dataSync),
            initialDelay,
            period,
            unit
        );
    }
    
    /**
     * 固定延迟调度
     */
    private ScheduledFuture<?> scheduleFixedDelayTask(DataSync dataSync, DataSync.ScheduleConfig scheduleConfig) {
        long delay = scheduleConfig.getIntervalSeconds() != null ? scheduleConfig.getIntervalSeconds() : 60;
        String timeUnit = "SECONDS";
        long initialDelay = 0;
        
        TimeUnit unit = parseTimeUnit(timeUnit);
        
        return scheduler.scheduleWithFixedDelay(
            () -> executeScheduledTask(dataSync),
            initialDelay,
            delay,
            unit
        );
    }
    
    /**
     * 一次性调度
     */
    private ScheduledFuture<?> scheduleOnceTask(DataSync dataSync, DataSync.ScheduleConfig scheduleConfig) {
        long delay = 0;
        String timeUnit = "SECONDS";
        
        TimeUnit unit = parseTimeUnit(timeUnit);
        
        return scheduler.schedule(
            () -> executeScheduledTask(dataSync),
            delay,
            unit
        );
    }
    
    /**
     * 执行调度任务
     */
    private void executeScheduledTask(DataSync dataSync) {
        try {
            logger.info("执行调度任务: {}", dataSync.getName());
            
            // 检查任务是否仍然启用和可调度
            DataSync currentSync = dataSyncService.getById(dataSync.getId(), dataSync.getTenantId());
            if (currentSync == null || !currentSync.isEnabled() || !currentSync.isScheduled()) {
                logger.info("任务已禁用或不可调度，取消执行: {}", dataSync.getName());
                cancelScheduledTask(dataSync.getId());
                return;
            }
            
            // 检查是否在执行时间窗口内
            if (!isInExecutionWindow(currentSync)) {
                logger.debug("不在执行时间窗口内，跳过执行: {}", dataSync.getName());
                return;
            }
            
            // 检查是否已有任务在运行
            if ("running".equals(currentSync.getExecutionStatus())) {
                logger.warn("任务正在运行中，跳过本次执行: {}", dataSync.getName());
                return;
            }
            
            // 执行同步任务
            boolean success = dataSyncExecutor.executeSync(
                currentSync.getId(),
                "SYSTEM",
                "系统调度",
                "scheduled"
            );
            
            if (success) {
                logger.info("调度任务执行成功: {}", dataSync.getName());
            } else {
                logger.error("调度任务执行失败: {}", dataSync.getName());
            }
            
        } catch (Exception e) {
            logger.error("执行调度任务异常: {}", dataSync.getName(), e);
        }
    }
    
    /**
     * 检查是否在执行时间窗口内
     */
    private boolean isInExecutionWindow(DataSync dataSync) {
        try {
            DataSync.ScheduleConfig scheduleConfig = dataSync.getScheduleConfigObject();
            if (scheduleConfig == null) {
                return true;
            }
            
            LocalDateTime now = LocalDateTime.now();
            
            // 检查开始时间和结束时间
            if (scheduleConfig.getStartTime() != null && now.isBefore(scheduleConfig.getStartTime())) {
                return false;
            }
            
            if (scheduleConfig.getEndTime() != null && now.isAfter(scheduleConfig.getEndTime())) {
                return false;
            }
            
            return true;
            
        } catch (Exception e) {
            logger.error("检查执行时间窗口失败", e);
            return true; // 出错时默认允许执行
        }
    }
    
    /**
     * 取消调度任务
     */
    public boolean cancelScheduledTask(String syncId) {
        ScheduledFuture<?> future = scheduledTasks.remove(syncId);
        if (future != null) {
            boolean cancelled = future.cancel(false);
            logger.info("取消调度任务: {} ({})", syncId, cancelled ? "成功" : "失败");
            return cancelled;
        }
        return false;
    }
    
    /**
     * 取消所有调度任务
     */
    public void cancelAllScheduledTasks() {
        for (String syncId : scheduledTasks.keySet()) {
            cancelScheduledTask(syncId);
        }
        logger.info("已取消所有调度任务");
    }
    
    /**
     * 重新调度任务
     */
    public boolean rescheduleTask(String syncId) {
        try {
            DataSync dataSync = dataSyncService.getById(syncId, null);
            if (dataSync == null) {
                return false;
            }
            
            // 取消现有调度
            cancelScheduledTask(syncId);
            
            // 重新调度
            return scheduleTask(dataSync);
        } catch (Exception e) {
            logger.error("重新调度任务失败: {}", syncId, e);
            return false;
        }
    }
    
    /**
     * 获取调度状态
     */
    public boolean isTaskScheduled(String syncId) {
        ScheduledFuture<?> future = scheduledTasks.get(syncId);
        return future != null && !future.isCancelled() && !future.isDone();
    }
    
    /**
     * 获取所有调度任务数量
     */
    public int getScheduledTaskCount() {
        return scheduledTasks.size();
    }
    
    /**
     * 解析Cron表达式为间隔秒数（简化实现）
     */
    private long parseCronToInterval(String cronExpression) {
        // 这里是简化实现，实际应该使用专业的Cron解析库
        // 默认返回5分钟间隔
        return 300;
    }
    
    /**
     * 解析时间单位
     */
    private TimeUnit parseTimeUnit(String timeUnit) {
        if (timeUnit == null) {
            return TimeUnit.SECONDS;
        }
        
        switch (timeUnit.toLowerCase()) {
            case "seconds":
            case "second":
            case "s":
                return TimeUnit.SECONDS;
            case "minutes":
            case "minute":
            case "m":
                return TimeUnit.MINUTES;
            case "hours":
            case "hour":
            case "h":
                return TimeUnit.HOURS;
            case "days":
            case "day":
            case "d":
                return TimeUnit.DAYS;
            default:
                return TimeUnit.SECONDS;
        }
    }
    
    /**
     * 定时检查和清理任务
     */
    @Scheduled(fixedRate = 300000) // 每5分钟执行一次
    public void cleanupTasks() {
        try {
            logger.debug("开始清理调度任务");
            
            // 清理已完成或取消的任务
            scheduledTasks.entrySet().removeIf(entry -> {
                ScheduledFuture<?> future = entry.getValue();
                return future.isCancelled() || future.isDone();
            });
            
            // 检查数据库中的任务状态，移除已禁用的任务
            for (String syncId : scheduledTasks.keySet()) {
                DataSync dataSync = dataSyncService.getById(syncId, null);
                if (dataSync == null || !dataSync.isEnabled() || !dataSync.isScheduled()) {
                    cancelScheduledTask(syncId);
                }
            }
            
            logger.debug("清理调度任务完成，当前活跃任务数: {}", scheduledTasks.size());
        } catch (Exception e) {
            logger.error("清理调度任务失败", e);
        }
    }
    
    /**
     * 定时重新加载任务
     */
    @Scheduled(fixedRate = 600000) // 每10分钟执行一次
    public void reloadTasks() {
        try {
            logger.debug("开始重新加载调度任务");
            
            // 获取所有启用的定时同步任务
            List<DataSync> scheduledSyncs = dataSyncService.getScheduledSyncs(null);
            
            // 检查是否有新的任务需要调度
            for (DataSync dataSync : scheduledSyncs) {
                if (!isTaskScheduled(dataSync.getId())) {
                    scheduleTask(dataSync);
                }
            }
            
            logger.debug("重新加载调度任务完成");
        } catch (Exception e) {
            logger.error("重新加载调度任务失败", e);
        }
    }
    
    /**
     * 手动触发任务执行
     */
    public boolean triggerTask(String syncId, String triggeredBy, String triggeredByName) {
        try {
            DataSync dataSync = dataSyncService.getById(syncId, null);
            if (dataSync == null) {
                return false;
            }
            
            // 异步执行任务
            scheduler.execute(() -> {
                dataSyncExecutor.executeSync(syncId, triggeredBy, triggeredByName, "manual");
            });
            
            return true;
        } catch (Exception e) {
            logger.error("手动触发任务失败: {}", syncId, e);
            return false;
        }
    }
    
    /**
     * 获取调度器状态
     */
    public Map<String, Object> getSchedulerStatus() {
        Map<String, Object> status = new HashMap<>();
        status.put("isShutdown", scheduler.isShutdown());
        status.put("isTerminated", scheduler.isTerminated());
        status.put("scheduledTaskCount", scheduledTasks.size());
        status.put("activeTaskCount", scheduledTasks.values().stream()
                .mapToInt(future -> future.isCancelled() || future.isDone() ? 0 : 1)
                .sum());
        return status;
    }
}